
import { RequestConfigType } from './../store/modules/chartEditStore/chartEditStore.d';
import { ref, toRefs, toRaw, inject, watch } from 'vue'
import type VChart from 'vue-echarts'
import cloneDeep from 'lodash/cloneDeep'
import { customizeHttp } from '@/api/http'
import { useChartDataPondFetch } from '@/hooks/'
import { CreateComponentType, ChartFrameEnum } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { RequestBodyEnum, RequestDataTypeEnum } from '@/enums/httpEnum'
import { isPreview, newFunctionHandle, intervalUnitHandle } from '@/utils'
import { setOption } from '@/packages/public/chart'


export function formatStr (s: string, values: any) {
    var reg = /\{([^\\{\\}]+)\}/gm;
    return s.replace(reg, function (match: any, name: string) {
        if(name in values)
            return values[name];

        return '';
    });
}

export const toArmRequest = (request: RequestConfigType, requestStrJSON: string, filters: any): RequestConfigType => {
  if(requestStrJSON.includes('{') && requestStrJSON.includes('}')) {
    var s: RequestConfigType = cloneDeep(request);
    if(s.requestUrl && s.requestUrl.includes('{') && s.requestUrl.includes('}')) {
      s.requestUrl = formatStr(s.requestUrl, filters);
    }
    if(s.requestParams.Header && Object.keys(s.requestParams.Header).length) {
      for(var k in Object.keys(s.requestParams.Header)) {
        var keyValue = s.requestParams.Header[k];
        if(keyValue && keyValue.includes('{') && keyValue.includes('}')) {
          s.requestParams.Header[k] = formatStr(keyValue, filters);
        }
      }
    }
    if(Object.keys(s.requestParams.Body).length) {
      if(s.requestParamsBodyType === RequestBodyEnum.JSON) {
        s.requestParams.Body['json'] = formatStr(s.requestParams.Body['json'], filters);
      } else if(s.requestParamsBodyType === RequestBodyEnum.XML) {
        s.requestParams.Body['xml'] = formatStr(s.requestParams.Body['xml'], filters);
      } else if(s.requestParamsBodyType === RequestBodyEnum.X_WWW_FORM_URLENCODED) {
        const bodyFormData = s.requestParams.Body['x-www-form-urlencoded']
        for (const i in bodyFormData) {
          bodyFormData[i] = formatStr(bodyFormData[i], filters);
        }
      } else if(s.requestParamsBodyType === RequestBodyEnum.FORM_DATA) {
        const bodyFormUrlencoded = s.requestParams.Body['form-data']
        for (const i in bodyFormUrlencoded) {
          bodyFormUrlencoded[i] = formatStr(bodyFormUrlencoded[i], filters);
        }
      }
    }

    // console.log(request);
    return s;
  }

  return request;
}

// 获取类型
type ChartEditStoreType = typeof useChartEditStore

/**
 * setdata 数据监听与更改
 * @param targetComponent
 * @param useChartEditStore 若直接引会报错，只能动态传递
 * @param updateCallback 自定义更新函数
 */
export const useChartDataFetch = (
  targetComponent: CreateComponentType,
  useChartEditStore: ChartEditStoreType,
  updateCallback?: (...args: any) => any
) => {
  const vChartRef = ref<typeof VChart | null>(null)
  let fetchInterval: any = 0

  // 数据池
  const { addGlobalDataInterface } = useChartDataPondFetch()

  // 组件类型
  const { chartFrame } = targetComponent.chartConfig

  // eCharts 组件配合 vChart 库更新方式
  const echartsUpdateHandle = (dataset: any) => {
    if (chartFrame === ChartFrameEnum.ECHARTS) {
      if (vChartRef.value) {
        setOption(vChartRef.value, { dataset: dataset })
      }
    } else if(vChartRef.value && vChartRef.value.setData) {
      vChartRef.value.setData(dataset)
    }
  }

  const { filters } = inject('filters', { filters: null }) as any;
  const requestStrJSON = JSON.stringify(targetComponent.request);
  if(filters) {
    watch(filters, () => {
      const name = filters.value['@@name'];
      if(name && requestStrJSON.includes(`{${name}}`)) {
        requestIntervalFn();
      }
    });
  }

  const requestIntervalFn = () => {
    const chartEditStore = useChartEditStore()

    // 全局数据
    const {
      requestOriginUrl,
      requestIntervalUnit: globalUnit,
      requestInterval: globalRequestInterval
    } = toRefs(chartEditStore.getRequestGlobalConfig)

    // 目标组件
    const {
      requestDataType,
      requestUrl,
      requestIntervalUnit: targetUnit,
      requestInterval: targetInterval
    } = toRefs(targetComponent.request)

    // 非请求类型
    if (requestDataType.value !== RequestDataTypeEnum.AJAX) return

    try {
      // 处理地址
      // @ts-ignore
      if (requestUrl?.value) {
        // requestOriginUrl 允许为空
        const completePath = requestOriginUrl && requestOriginUrl.value + requestUrl.value
        if (!completePath) return

        clearInterval(fetchInterval)

        const fetchFn = async () => {
          const res = await customizeHttp(toArmRequest(toRaw(targetComponent.request), requestStrJSON, filters.value), toRaw(chartEditStore.getRequestGlobalConfig))
          if (res) {
            try {
              const filter = targetComponent.filter
              echartsUpdateHandle(newFunctionHandle(res?.data, res, filter))
              // 更新回调函数
              if (updateCallback) {
                updateCallback(newFunctionHandle(res?.data, res, filter))
              }
            } catch (error) {
              console.error(error)
            }
          }
        }

        // 立即调用
        fetchFn()
        // 定时时间
        const time = targetInterval && targetInterval.value ? targetInterval.value : 0 /*globalRequestInterval.value*/
        // 单位
        const unit = targetInterval && targetInterval.value ? targetUnit.value : globalUnit.value
        // 开启轮询
        if (time) fetchInterval = setInterval(fetchFn, intervalUnitHandle(time, unit))
      }
      // eslint-disable-next-line no-empty
    } catch (error) {
      console.log(error)
    }
  }

  // if (isPreview()) {
    // 判断是否是数据池类型
    targetComponent.request.requestDataType === RequestDataTypeEnum.Pond
      ? addGlobalDataInterface(targetComponent, useChartEditStore, updateCallback || echartsUpdateHandle)
      : requestIntervalFn()
  // }
  return { vChartRef }
}
